﻿#region Disclaimer/Info
///////////////////////////////////////////////////////////////////////////////////////////////////
// MetaCollection
// 
// MetaCollection is a system to provide a standard structure, permissions and metadata service
// for content organization.
//
// This project is hosted at Google Code at http://code.google.com/p/metacollection/
//
// This project is licensed under the BSD license.  See the License.txt file for more information.
///////////////////////////////////////////////////////////////////////////////////////////////////
#endregion

using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Web.Script.Serialization;
using System.Xml.Linq;
using MetaCollection.Framework.Change;
using MetaCollection.Framework.Model;

namespace MetaCollection.Framework.Repository
{
	/// <summary>
	/// An item repository built on an XML file.
	/// </summary>
	/// <remarks>
	/// This is the rough file format
	/// ItemRepository
	///    ItemCollection
	///        ItemInstance
	///        ItemInstance
	///        ItemInstance
	///    /ItemCollection
	///    ResourceTypes
	///        ResourceProvider
	///        ResourceProvider
	///    /ResourceTypes
	/// /ItemRepository
	/// </remarks>
	public class XItemRepository : IItemRepository
	{
		private string m_FileName;
		private XElement m_Items;
		private XElement m_ResourceTypes;
		private XDocument m_ItemDocument;
		private const string ITEMNAMESPACE = "uri://MetaCollection/v2/";
		private bool m_Initialized;

		#region Constructors

		/// <summary>
		/// Initializes a new instance of the <see cref="ItemXmlRepository"/> class.
		/// </summary>
		public XItemRepository()
		{
			m_ItemDocument = new XDocument();
			XElement docRoot = new XElement(XName.Get("ItemInstance", ITEMNAMESPACE));
			m_Items = new XElement(XName.Get("ItemCollection", ITEMNAMESPACE));
			m_ResourceTypes = new XElement(XName.Get("ResourceTypes", ITEMNAMESPACE));
			docRoot.Add(m_Items);
			docRoot.Add(m_ResourceTypes);
			m_ItemDocument.Document.Add(docRoot);
		}

		/// <summary>
		/// Releases unmanaged resources and performs other cleanup operations before the
		/// <see cref="ItemXmlRepository"/> is reclaimed by garbage collection.
		/// </summary>
		/// <remarks>A file opened wit hthe ItemXmlRepository(string fileName) constructor will
		/// be used to save any changes made.</remarks>
		~XItemRepository()
		{
//			if (!String.IsNullOrEmpty(m_FileName))
//				m_ItemDocument.Save(m_FileName);
		}

		/// <summary>
		/// Initializes a new instance of the <see cref="ItemXmlRepository"/> class.
		/// </summary>
		/// <param name="reader">A text reader to read the ItemInstances from</param>
		public XItemRepository(TextReader reader)
		{
			if (reader == null)
				throw new ArgumentNullException("reader");

			m_ItemDocument = XDocument.Load(reader);
			FillFromDocument(m_ItemDocument);
		}

		/// <summary>
		/// Initializes a new instance of the <see cref="ItemXmlRepository"/> class.
		/// </summary>
		/// <param name="fileName">Name of the file.</param>
		public XItemRepository(string fileName)
		{
			if (String.IsNullOrEmpty(fileName) || !File.Exists(fileName))
				throw new ArgumentException("A valid fileName is required", "fileName");

			m_FileName = fileName;
			m_ItemDocument = XDocument.Load(m_FileName);

			FillFromDocument(m_ItemDocument);
		}

		public void Initialize(string configData)
		{
			if (m_Initialized)
				throw new InvalidOperationException("This repository has already been initialized.");
			m_Initialized = true;

			if (String.IsNullOrEmpty(configData) || !File.Exists(configData))
				throw new ArgumentException("A valid fileName is required", "configData");

			m_FileName = configData;
			m_ItemDocument = XDocument.Load(m_FileName);

			FillFromDocument(m_ItemDocument);
		}

		private void FillFromDocument(XDocument document)
		{
			if (document == null)
				throw new ArgumentNullException("document", "Unable to fill items from document, it is null.");

			m_Items = document.Descendants("ItemCollection").First();
			m_ResourceTypes = document.Descendants("ResourceTypes").First();


			if ((m_Items == null) || (m_ResourceTypes == null))
				throw new ArgumentException("Invalid Document Format.  Document must contain an Item Collection and a Resource Type collection.", "document");

			// TODO : more checking of the file format.
		}



		#endregion

		/// <summary>
		/// Saves the repository instance to the given textwriter.
		/// </summary>
		/// <param name="writer">An initialized text writer to persist the ItemInstances in</param>
		public void SaveRepository(TextWriter writer)
		{
			if (writer == null)
				throw new ArgumentNullException("writer");
			m_ItemDocument.Save(writer);
		}


		/// <summary>
		/// Converts XML into an item instance.
		/// </summary>
		/// <param name="xmlItem">The XML.</param>
		/// <returns>An instance of an item hydrated from the XML in <paramref name="xmlItem"/></returns>
		public static IItemInstance XmlToItemInstance(XContainer xmlItem)
		{
			IItemInstance item = new ItemInstance();
			item.Id = new Guid(xmlItem.Element(XName.Get("Id", ITEMNAMESPACE)).Value);
			item.ParentId = new Guid(xmlItem.Element(XName.Get("ParentId", ITEMNAMESPACE)).Value);
			item.ExternalId = xmlItem.Element(XName.Get("ExternalId", ITEMNAMESPACE)).IsEmpty ? null : xmlItem.Element(XName.Get("ExternalId", ITEMNAMESPACE)).Value;
			item.Version = Convert.ToInt32(xmlItem.Element(XName.Get("Version", ITEMNAMESPACE)).Value, CultureInfo.CurrentCulture);
			item.LeftVersion = xmlItem.Element(XName.Get("LeftVersion", ITEMNAMESPACE)).IsEmpty ? (int?)null : Convert.ToInt32(xmlItem.Element(XName.Get("LeftVersion", ITEMNAMESPACE)).Value, CultureInfo.CurrentCulture);
			item.RightVersion = xmlItem.Element(XName.Get("RightVersion", ITEMNAMESPACE)).IsEmpty ? (int?)null : Convert.ToInt32(xmlItem.Element(XName.Get("RightVersion", ITEMNAMESPACE)).Value, CultureInfo.CurrentCulture);
			item.CreatedBy = xmlItem.Element(XName.Get("CreatedBy", ITEMNAMESPACE)).IsEmpty ? null : xmlItem.Element(XName.Get("CreatedBy", ITEMNAMESPACE)).Value;
			item.Comment = xmlItem.Element(XName.Get("Comment", ITEMNAMESPACE)).IsEmpty ? null : xmlItem.Element(XName.Get("Comment", ITEMNAMESPACE)).Value;
			item.Name = xmlItem.Element(XName.Get("Name", ITEMNAMESPACE)).IsEmpty ? null : xmlItem.Element(XName.Get("Name", ITEMNAMESPACE)).Value;
			item.Published = Convert.ToBoolean(xmlItem.Element(XName.Get("Published", ITEMNAMESPACE)).Value, CultureInfo.CurrentCulture);
			item.MimeType = xmlItem.Element(XName.Get("MimeType", ITEMNAMESPACE)).IsEmpty ? null : xmlItem.Element(XName.Get("MimeType", ITEMNAMESPACE)).Value;
			item.Specification = new Guid(xmlItem.Element(XName.Get("ResourceProvider", ITEMNAMESPACE)).Value);
			//item.LastModified = DateTime.Parse(xmlItem.Element(XName.Get("LastModified", ITEMNAMESPACE)).Value, CultureInfo.CurrentCulture);
            item.LastModified = DateTime.Parse((xmlItem.Element(XName.Get("LastModified", ITEMNAMESPACE)).IsEmpty ? DateTime.Now.ToString() : xmlItem.Element(XName.Get("LastModified", ITEMNAMESPACE)).Value), CultureInfo.CurrentCulture);
			item.Properties = XmlToItemProperties(xmlItem.Element(XName.Get("Properties", ITEMNAMESPACE)).Elements());
			item.AccessClaims = XmlToItemClaims(xmlItem.Element(XName.Get("AccessClaims", ITEMNAMESPACE)).Elements());
			item.Relationships = XmlToItemRelationships(xmlItem.Element(XName.Get("Relationships", ITEMNAMESPACE)).Elements());
            item.ItemClaimId = item.AccessClaims.First().Id; 
			return item;
		}



		/// <summary>
		/// XMLs to item properties.
		/// </summary>
		/// <param name="xel">The xel.</param>
		/// <returns></returns>
		private static IEnumerable<IItemProperty> XmlToItemProperties(IEnumerable<XElement> xel)
		{
			List<IItemProperty> properties = new List<IItemProperty>();
			foreach (XElement x in xel)
			{
				IItemProperty property = new ItemProperty();
				property.KeyName = x.Element(XName.Get("KeyName", ITEMNAMESPACE)).IsEmpty ? null : x.Element(XName.Get("KeyName", ITEMNAMESPACE)).Value;
				property.KeyValue = x.Element(XName.Get("KeyValue", ITEMNAMESPACE)).IsEmpty ? null : x.Element(XName.Get("KeyValue", ITEMNAMESPACE)).Value;
				properties.Add(property);
			}
			return properties;
		}

		/// <summary>
		/// XMLs to item claims.
		/// </summary>
		/// <param name="xel">The xel.</param>
		/// <returns></returns>
		private static IEnumerable<IItemClaim> XmlToItemClaims(IEnumerable<XElement> xel)
		{
			List<IItemClaim> claims = new List<IItemClaim>();
			foreach (XElement x in xel)
			{
				IItemClaim claim = new ItemClaim();
				claim.Id = new Guid(x.Element(XName.Get("Id", ITEMNAMESPACE)).Value);
				claim.ClaimType = x.Element(XName.Get("ClaimType", ITEMNAMESPACE)).IsEmpty ? null : x.Element(XName.Get("ClaimType", ITEMNAMESPACE)).Value;
				claim.ClaimValue = x.Element(XName.Get("ClaimValue", ITEMNAMESPACE)).IsEmpty ? null : x.Element(XName.Get("ClaimValue", ITEMNAMESPACE)).Value;
				claim.Rights = (AccessRights)Enum.Parse(typeof(AccessRights), x.Element(XName.Get("Rights", ITEMNAMESPACE)).Value, true);
				claims.Add(claim);
			}
			return claims;
		}

		/// <summary>
		/// XMLs to item relationships.
		/// </summary>
		/// <param name="xel">The xel.</param>
		/// <returns></returns>
		private static IEnumerable<IItemRelationship> XmlToItemRelationships(IEnumerable<XElement> xel)
		{
			List<IItemRelationship> relationships = new List<IItemRelationship>();
			foreach (XElement x in xel)
			{
				IItemRelationship relationship = new ItemRelationship();
				relationship.State = x.Element(XName.Get("State", ITEMNAMESPACE)).IsEmpty ? null : x.Element(XName.Get("State", ITEMNAMESPACE)).Value;
				relationship.TargetItem = new Uri(x.Element(XName.Get("TargetItem", ITEMNAMESPACE)).Value);
				relationship.RelationshipType = x.Element(XName.Get("RelationshipType", ITEMNAMESPACE)).IsEmpty ? null : x.Element(XName.Get("RelationshipType", ITEMNAMESPACE)).Value;
				relationships.Add(relationship);
			}
			return relationships;
		}

		#region IItemRepository Members

		public void RemoveItem(Guid id)
		{
			throw new NotImplementedException();
		}

		public void RemoveItem(Guid id, int version)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Gets all versions of an item
		/// </summary>
		/// <param name="id">The id of the item.</param>
		/// <param name="options"></param>
		/// <returns>
		/// An ItemInstance for the given Item Id or null if no object found
		/// </returns>
		public IEnumerable<IItemInstance> GetItem(Guid id, MetaCollection.Framework.Model.LoadOptions options)
		{
			if (id == null)
				throw new ArgumentNullException("id");

			var q = from itemXml in m_Items.Descendants(XName.Get("ItemInstance", ITEMNAMESPACE))
					where itemXml.Descendants(XName.Get("Id", ITEMNAMESPACE)).First().Value == id.ToString("D")
					select XmlToItemInstance(itemXml);
			return q.AsQueryable<IItemInstance>();
		}

		/// <summary>
		/// Gets an Item.
		/// </summary>
		/// <param name="id">The id.</param>
		/// <param name="version">The version.</param>
		/// <param name="opt">The option.</param>
		/// <returns>
		/// An ItemInstance for the given Item Id-Version or null if no object found
		/// </returns>
		public IItemInstance GetItem(Guid id, int version, MetaCollection.Framework.Model.LoadOptions opt)
		{
			if (id == null)
				throw new ArgumentNullException("id");

			var q = from itemXml in m_Items.Descendants(XName.Get("ItemInstance", ITEMNAMESPACE))
					where (itemXml.Descendants(XName.Get("Id", ITEMNAMESPACE)).First().Value.Equals(id.ToString("D"), StringComparison.OrdinalIgnoreCase)
					&&
					itemXml.Descendants(XName.Get("Version", ITEMNAMESPACE)).First().Value == version.ToString(CultureInfo.InvariantCulture))
					select XmlToItemInstance(itemXml);

			return q.FirstOrDefault();
		}

		/// <summary>
		/// Finds all the items with a given parent.
		/// </summary>
		/// <param name="parentId">The parent id.</param>
		/// <param name="includeIndirect">if set to <c>true</c> the children that are not directly under the parent are also included.</param>
		/// <param name="opt">Load Options for what data to return</param>
		/// <returns></returns>
		/// <remarks>Returns the published version ?? max(version) of each item</remarks>
		public IEnumerable<IItemInstance> FindByParent(Guid parentId, bool includeIndirect, MetaCollection.Framework.Model.LoadOptions opt)
		{
			if (parentId == null)
				throw new ArgumentNullException("parentId");

			var q = from itemXml in m_Items.Descendants(XName.Get("ItemInstance", ITEMNAMESPACE))
					where itemXml.Descendants(XName.Get("ParentId", ITEMNAMESPACE)).First().Value.Equals(parentId.ToString())
					select XmlToItemInstance(itemXml);
			return q.AsEnumerable<IItemInstance>();
		}

		/// <summary>
		/// Puts the item into persistant storage
		/// </summary>
		/// <param name="item"></param>
		/// TODO: Implement change collection & level
		public IItemInstance SaveItem(IItemInstance item, ItemChangeCollection changeCollection)
		{
			if (item == null)
				throw new ArgumentNullException("item");

			XNode xe = item.ToXml();
			m_Items.Add(xe);
			return item;
		}

		public IEnumerable<IItemInstance> FindByProperty(string keyName, string KeyValue, MetaCollection.Framework.Model.LoadOptions opt)
		{
			throw new NotImplementedException();
		}


		public IEnumerable<IItemInstance> FindByRelationship(Uri targetItem, string relationshipType, MetaCollection.Framework.Model.LoadOptions opt)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Removes an item from persistent storage
		/// </summary>
		/// <param name="item"></param>
		public void Remove(IItemInstance item)
		{
			m_Items.Descendants(XName.Get("ItemInstance", ITEMNAMESPACE)).FirstOrDefault
			(i =>
				i.Descendants(XName.Get("Id", ITEMNAMESPACE)).First().Value.Equals(item.Id.ToString("D"), StringComparison.OrdinalIgnoreCase)
				&& i.Descendants(XName.Get("Version", ITEMNAMESPACE)).First().Value == item.Version.ToString(CultureInfo.InvariantCulture)
			).Remove();
		}

		/// <summary>
		/// Replaces an item in persistent storage
		/// </summary>
		/// <param name="previousItem"></param>
		/// <param name="updatedItem"></param>
		public void Replace(IItemInstance previousItem, IItemInstance updatedItem)
		{
			m_Items.Descendants(XName.Get("ItemInstance", ITEMNAMESPACE)).FirstOrDefault
			(i =>
				i.Descendants(XName.Get("Id", ITEMNAMESPACE)).First().Value.Equals(previousItem.Id.ToString("D"), StringComparison.OrdinalIgnoreCase)
				&& i.Descendants(XName.Get("Version", ITEMNAMESPACE)).First().Value == previousItem.Version.ToString(CultureInfo.InvariantCulture)
			).ReplaceWith(updatedItem.ToXml());
		}

		/// <summary>
		/// Finds an item by name with a given parent.
		/// </summary>
		/// <param name="parentId">The parent id.</param>
		/// <param name="name">The name.</param>
		/// <param name="opt">Load Options for what data to return</param>
		/// <returns>an ItemInstance</returns>
		/// <remarks>Returns the published version ?? max(version) of each item</remarks>
		public IEnumerable<IItemInstance> FindByName(Guid parentId, string name, MetaCollection.Framework.Model.LoadOptions opt)
		{
			if (parentId == null)
				throw new ArgumentNullException("parentId");
			if (string.IsNullOrEmpty(name))
				throw new ArgumentNullException("name");

			var q = from itemXml in m_Items.Descendants(XName.Get("ItemInstance", ITEMNAMESPACE))
					where (itemXml.Descendants(XName.Get("Name", ITEMNAMESPACE)).First().Value.Equals(name.Trim('/'), StringComparison.OrdinalIgnoreCase)
					&& itemXml.Descendants(XName.Get("ParentId", ITEMNAMESPACE)).First().Value.Equals(parentId.ToString("D"), StringComparison.OrdinalIgnoreCase))
					select XmlToItemInstance(itemXml);
			return q.AsEnumerable<IItemInstance>();
		}

		/// <summary>
		/// Finds all items by name.
		/// </summary>
		/// <param name="query">The query.</param>
		/// <param name="option">Load Options for what data to return</param>
		/// <returns></returns>
		public IEnumerable<IItemInstance> Find(Expression<Func<IItemInstance, bool>> query, MetaCollection.Framework.Model.LoadOptions opt)
		{
			if (query == null)
				throw new ArgumentNullException("query");

			var q = from itemXml in m_Items.Descendants(XName.Get("ItemInstance", ITEMNAMESPACE))
					where query.Compile().Invoke(XmlToItemInstance(itemXml))
					select XmlToItemInstance(itemXml);
			return q.AsEnumerable<IItemInstance>();
		}

		#endregion
	}

	public static class ItemInstanceExtension
	{
		private const string ITEMNAMESPACE = "uri://MetaCollection/v2/";

		#region "ToXml"
		public static XElement ToXml(this IItemInstance item)
		{
			if (item == null)
				throw new ArgumentNullException("item");

			return new XElement(XName.Get("ItemInstance", ITEMNAMESPACE),
				new XElement(XName.Get("Id", ITEMNAMESPACE), item.Id),
				new XElement(XName.Get("ExternalId", ITEMNAMESPACE), item.ExternalId),
				new XElement(XName.Get("ParentId", ITEMNAMESPACE), item.ParentId),
				new XElement(XName.Get("Version", ITEMNAMESPACE), item.Version),
				new XElement(XName.Get("LeftVersion", ITEMNAMESPACE), item.LeftVersion),
				new XElement(XName.Get("RightVersion", ITEMNAMESPACE), item.RightVersion),
				new XElement(XName.Get("CreatedBy", ITEMNAMESPACE), item.CreatedBy),
				new XElement(XName.Get("Comment", ITEMNAMESPACE), item.Comment),
				new XElement(XName.Get("Name", ITEMNAMESPACE), item.Name),
				new XElement(XName.Get("Published", ITEMNAMESPACE), item.Published),
				new XElement(XName.Get("MimeType", ITEMNAMESPACE), item.MimeType),
				new XElement(XName.Get("ResourceProvider", ITEMNAMESPACE), item.Specification),
				new XElement(XName.Get("LastModified", ITEMNAMESPACE), item.LastModified),
				new XElement(XName.Get("Properties", ITEMNAMESPACE), SelectProperties(item.Properties)),
				new XElement(XName.Get("AccessClaims", ITEMNAMESPACE), SelectAccessClaims(item.AccessClaims)),
				new XElement(XName.Get("Relationships", ITEMNAMESPACE), SelectRelationships(item.Relationships)));
		}

		/// <summary>
		/// Selects the provider type properties into XElements
		/// </summary>
		/// <param name="provider">The provider type.</param>
		/// <returns>an xelement containing xelements for each property of the provider type</returns>
		public static XElement ToXml(this IProviderType provider)
		{
			if (provider == null)
				throw new ArgumentNullException("provider");

			return new XElement(XName.Get("ItemInstance", ITEMNAMESPACE),
				new XElement(XName.Get("AssemblyName", ITEMNAMESPACE), provider.AssemblyName),
				new XElement(XName.Get("Config", ITEMNAMESPACE), provider.Config),
				new XElement(XName.Get("Name", ITEMNAMESPACE), provider.Name)
				);

		}

		/// <summary>
		/// Selects the properties into XElements
		/// </summary>
		/// <param name="claims">The properties.</param>
		/// <returns>a collection of xelement itemproperties or null if empty</returns>
		private static IEnumerable<XElement> SelectProperties(IEnumerable<IItemProperty> properties)
		{
			if (properties == null)
				return null;
			return from prop in properties
				   select
					   new XElement(XName.Get("ItemProperty", ITEMNAMESPACE),
					   new XElement(XName.Get("KeyName", ITEMNAMESPACE), prop.KeyName),
					   new XElement(XName.Get("KeyValue", ITEMNAMESPACE), prop.KeyValue)
					   );
		}

		/// <summary>
		/// Selects the access claims into XElements
		/// </summary>
		/// <param name="claims">The claims.</param>
		/// <returns>a collection of xelement itemclaims or null if empty</returns>
		private static IEnumerable<XElement> SelectAccessClaims(IEnumerable<IItemClaim> claims)
		{
			if (claims == null)
				return null;

			return from claim in claims
				   select
					   new XElement(XName.Get("AccessClaim", ITEMNAMESPACE),
					   new XElement(XName.Get("Id", ITEMNAMESPACE), claim.Id),
					   new XElement(XName.Get("ClaimType", ITEMNAMESPACE), claim.ClaimType),
					   new XElement(XName.Get("ClaimValue", ITEMNAMESPACE), claim.ClaimValue),
					   new XElement(XName.Get("Rights", ITEMNAMESPACE), claim.Rights)
					   );
		}

		/// <summary>
		/// Selects the relationships into XElements
		/// </summary>
		/// <param name="relationships">The relationships.</param>
		/// <returns>a collection of xelement itemrelationships or null if empty</returns>
		private static IEnumerable<XElement> SelectRelationships(IEnumerable<IItemRelationship> relationships)
		{
			if (relationships == null)
				return null;
			return from rel in relationships
				   select
					   new XElement(XName.Get("Relationship", ITEMNAMESPACE),
					   new XElement(XName.Get("TargetItem", ITEMNAMESPACE), rel.TargetItem),
					   new XElement(XName.Get("RelationshipType", ITEMNAMESPACE), rel.RelationshipType),
					   new XElement(XName.Get("State", ITEMNAMESPACE), rel.State)
					   );
		}
		#endregion


		public static string ToJson(this IEnumerable<IItemInstance> items)
		{
			StringBuilder str = new StringBuilder("[");
			foreach (var item in items)
			{
				str.Append(item.ToJson());
				str.Append(", ");
			}
			str.Remove(str.ToString().LastIndexOf(","), 2);
			string rtn = str.Append("]").ToString(); 
			return rtn;
		}

		/// <summary>
		/// Returns json string representation of the item.
		/// </summary>
		/// <param name="item">The item.</param>
		/// <returns></returns>
		public static string ToJson(this IItemInstance item)
		{
			var cleanItem = new
			{
				ItemInstance = new
				{
					Id = item.Id,
					ExternalId = item.ExternalId,
					ParentId = item.ParentId,
					Version = item.Version,
					LeftVersion = item.LeftVersion,
					RightVersion = item.RightVersion,
					CreatedBy = item.CreatedBy,
					Comment = item.Comment,
					Name = item.Name,
					Published = item.Published,
					MimeType = item.MimeType,
					ResourceProvider = item.Specification,
					LastModified = item.LastModified,
					Properties = new List<object>(),
					Relationships = new List<object>(),
					AccessClaims = new List<object>(),
				}
			};

			if (item.Properties != null && item.Properties.Count() > 0)
			{
				foreach (var property in item.Properties)
				{
					cleanItem.ItemInstance.Properties.Add(new
					{
						Property = new { KeyName = property.KeyName, KeyValue = property.KeyValue }
					});
				}
			}

			if (item.Relationships != null && item.Relationships.Count() > 0)
			{
				foreach (var relationship in item.Relationships)
				{
					cleanItem.ItemInstance.Relationships.Add(new
					{
						Relationship = new { RelationshipType = relationship.RelationshipType, State = relationship.State, TargetItem = relationship.TargetItem }
					});
				}
			}

			if (item.AccessClaims != null && item.AccessClaims.Count() > 0)
			{
				foreach (var claim in item.AccessClaims)
				{
					cleanItem.ItemInstance.AccessClaims.Add(new
					{
						AccessClaim = new { Id = claim.Id, ClaimType = claim.ClaimType, ClaimValue = claim.ClaimValue, Rights = claim.Rights }
					});
				}
			}

			JavaScriptSerializer serializer = new JavaScriptSerializer();
			return serializer.Serialize(cleanItem);
		}
	}


}
